#include "utilities.h"

//This is the code for the write function which will write it to the corresponding socket.
void *writefun(void *ptr)
{
	struct timeval writetime;
	bool dieWrite = false;
	writeStruct wrStruct = *((writeStruct*) ptr);
	if(printFlag==1)
	{
		printf("Write Thread for Portnumber %d Starts\n",wrStruct.portNumber);
	}
	while(!dieWrite&&!dieChild)
	{
		pthread_mutex_lock(&writeMapMutex);
		writeListData listDataStr = writeMap[wrStruct.portNumber];
		if(!listDataStr.response.empty())
		{
			if((uint8_t)listDataStr.response.front().listBuff[0] == 0xCC || (uint8_t)listDataStr.response.front().listBuff[0] == 0xDB)
			{
				if(printFlag == 1)
				{
					printf("WRITE TYPE --- %02x\n",(uint8_t)listDataStr.response.front().listBuff[0]);
				}
				int logbuffflag=0;
				listBuffStruct writeBuff;
				listBuffStruct writeLogBuff;
				memset(&writeBuff.listBuff,'\0',listDataStr.response.front().datalength);
				memcpy(&writeBuff.listBuff,listDataStr.response.front().listBuff, 27);
				memcpy(&writeLogBuff.listBuff,listDataStr.response.front().listBuff, 27);
				writeBuff.datalength = listDataStr.response.front().datalength;
				writeBuff.logtype = listDataStr.response.front().logtype;
				writeLogBuff.logtype = listDataStr.response.front().logtype;
				listDataStr.response.pop_front();
				writeMap[wrStruct.portNumber] = listDataStr;
				pthread_mutex_unlock(&writeMapMutex);
				msg_header storeReq;
				fillMsgHdrStructure(storeReq,writeBuff.listBuff);
				if(dieChild)
				{
					if(printFlag==1)
					{
						cout<<"Write inside closed - "<<wrStruct.portNumber<<endl;
					}
					close(wrStruct.sock);
					pthread_exit(NULL);
				}
				if(write(wrStruct.sock,writeBuff.listBuff,27)==-1)
				{
					pthread_mutex_lock(&writeMapMutex);
					writeMap.erase(writeMap.find(wrStruct.portNumber));
					pthread_mutex_unlock(&writeMapMutex);
					if(printFlag==1)
					{
						cout<<"Write closed - "<<wrStruct.portNumber<<endl;
					}
					close(wrStruct.sock);
					pthread_exit(NULL);
				}
				int forCounter = storeReq.datalength/(8192);
				int extraCounter = storeReq.datalength%(8192);
				if(printFlag == 1)
				{
					printf("%s\n",&(listDataStr.response.front().listBuff[24]));
				}
				if(forCounter==0)
				{
					pthread_mutex_lock(&writeMapMutex);
					memset(&writeBuff.listBuff,'\0',8192);
					memcpy(writeBuff.listBuff,listDataStr.response.front().listBuff,storeReq.datalength);
					if(logbuffflag==0)
					{
					memcpy(&(writeLogBuff.listBuff[27]),listDataStr.response.front().listBuff,30);
					logbuffflag=1;
					}
					listDataStr.response.pop_front();
					writeMap[wrStruct.portNumber] = listDataStr;
					pthread_mutex_unlock(&writeMapMutex);
					if(write(wrStruct.sock,writeBuff.listBuff,storeReq.datalength)==-1)
					{
						pthread_mutex_lock(&writeMapMutex);
						writeMap.erase(writeMap.find(wrStruct.portNumber));
						pthread_mutex_unlock(&writeMapMutex);
						if(printFlag==1)
						{
							cout<<"Write closed - "<<wrStruct.portNumber<<endl;
						}
						close(wrStruct.sock);
						pthread_exit(NULL);
					}
				}
				else
				{
					int f = 0;
					for(f=0;f<forCounter;f++)
					{	
						pthread_mutex_lock(&writeMapMutex);
						memset(&writeBuff.listBuff,'\0',8192);
						memcpy(writeBuff.listBuff,listDataStr.response.front().listBuff,listDataStr.response.front().datalength);
						if(logbuffflag==0)
						{
						memcpy(&(writeLogBuff.listBuff[27]),listDataStr.response.front().listBuff,30);
						logbuffflag=1;
						}
						writeBuff.datalength = listDataStr.response.front().datalength;
						listDataStr.response.pop_front();
						writeMap[wrStruct.portNumber] = listDataStr;
						pthread_mutex_unlock(&writeMapMutex);
						if(write(wrStruct.sock,writeBuff.listBuff,writeBuff.datalength)==-1)
						{
							pthread_mutex_lock(&writeMapMutex);
							writeMap.erase(writeMap.find(wrStruct.portNumber));
							pthread_mutex_unlock(&writeMapMutex);
							if(printFlag==1)
							{
								cout<<"Write closed - "<<wrStruct.portNumber<<endl;
							}
							close(wrStruct.sock);
							pthread_exit(NULL);
						}
						
					}
						
					if(extraCounter!=0)
					{
						pthread_mutex_lock(&writeMapMutex);
						memset(&writeBuff.listBuff,'\0',8192);
						memcpy(writeBuff.listBuff,listDataStr.response.front().listBuff,listDataStr.response.front().datalength);
						writeBuff.datalength = listDataStr.response.front().datalength;
						listDataStr.response.pop_front();
						writeMap[wrStruct.portNumber] = listDataStr;
						pthread_mutex_unlock(&writeMapMutex);
						if(write(wrStruct.sock,writeBuff.listBuff,writeBuff.datalength)==-1)
						{
							pthread_mutex_lock(&writeMapMutex);
							writeMap.erase(writeMap.find(wrStruct.portNumber));
							pthread_mutex_unlock(&writeMapMutex);
							if(printFlag==1)
							{
								cout<<"Write closed - "<<wrStruct.portNumber<<endl;
							}
							close(wrStruct.sock);
							pthread_exit(NULL);
						}
					}
				}
				gettimeofday(&writetime,NULL);
				writeLogBuff.datalength = 27+storeReq.datalength;
				writeLogBuff.portNumber = wrStruct.portNumber;
				write_to_log(writeLogBuff,writeLogBuff.logtype,writetime);
			}
			else if(!notifyFlag || (uint8_t)listDataStr.response.front().listBuff[0] == 0xf7)
			{
				if((uint8_t)listDataStr.response.front().listBuff[0] != 0xf8)
				{
					if(printFlag==1)
					{
						cout<<"Write th - "<<wrStruct.portNumber<<endl;
						cout<<"Write port - "<<wrStruct.sock<<endl;
						printf("%02x\n",(uint8_t)listDataStr.response.front().listBuff[0]);
					}
					for(int i=0; i<20; i++)
					{
						if(printFlag==1)
						{
							printf("%02x", (uint8_t)(listDataStr.response.front().listBuff[i+1]));
						}
					}
					if(printFlag==1)
					{
						cout<<endl;
					}
					uint8_t ttls;
					memcpy(&ttls, &(listDataStr.response.front().listBuff[21]), sizeof(uint8_t));
					if(printFlag==1)
					{
						printf("%d\n",ttls);
						printf("%d\n",listDataStr.response.front().listBuff[22]);
					}
					uint32_t temp;
					memcpy(&temp, &(listDataStr.response.front().listBuff[23]), sizeof(uint32_t));
					if(printFlag==1)
					{
						printf("%d\n",temp);
					}
				}
				else if((uint8_t)listDataStr.response.front().listBuff[0] == 0xf8)
				{
					//cout<<"KPAL"<<endl;
				}
				listBuffStruct writeBuff;
				memset(&writeBuff, '\0',listDataStr.response.front().datalength);
				memcpy(&writeBuff,listDataStr.response.front().listBuff, listDataStr.response.front().datalength);
				writeBuff.datalength = listDataStr.response.front().datalength;
				writeBuff.logtype = listDataStr.response.front().logtype;
				listDataStr.response.pop_front();
				writeMap[wrStruct.portNumber] = listDataStr;
				pthread_mutex_unlock(&writeMapMutex);
				if(dieChild)
				{
					if(printFlag==1)
					{
						cout<<"Write inside closed - "<<wrStruct.portNumber<<endl;
					}
					close(wrStruct.sock);
					pthread_exit(NULL);
				}
				if(write(wrStruct.sock,writeBuff.listBuff,writeBuff.datalength)==-1)
				{
					pthread_mutex_lock(&writeMapMutex);
					writeMap.erase(writeMap.find(wrStruct.portNumber));
					pthread_mutex_unlock(&writeMapMutex);
					if(printFlag==1)
					{
						cout<<"Write closed - "<<wrStruct.portNumber<<endl;
					}
					close(wrStruct.sock);
					pthread_exit(NULL);
				}
				gettimeofday(&writetime,NULL);
				writeBuff.portNumber = wrStruct.portNumber;
				write_to_log(writeBuff,writeBuff.logtype,writetime);
			}
			else
			{
				pthread_mutex_unlock(&writeMapMutex);
				usleep(1);
			}
		}
		else
		{
			pthread_mutex_unlock(&writeMapMutex);
			usleep(1);
		}
	pthread_mutex_lock(&writeMapMutex);
	listDataStr = writeMap[wrStruct.portNumber];
	dieWrite = listDataStr.dieflag;
	pthread_mutex_unlock(&writeMapMutex);

	}
	if(printFlag==1)
	{
		cout<<"Write closed end- "<<wrStruct.portNumber<<endl;
	}
	pthread_mutex_lock(&writeMapMutex);
	if(writeMap.find(wrStruct.portNumber) != writeMap.end())
	{
		writeMap.erase(writeMap.find(wrStruct.portNumber));
	}
	if(printFlag==1)
	{
		cout<<"map erased"<<endl;
	}
	pthread_mutex_unlock(&writeMapMutex);
	close(wrStruct.sock);
	pthread_exit(NULL);
}
